﻿//-----------------------------------------------------------------------
// <copyright file="CommandLineArguments.cs" company="Microsoft">
//     Copyright (c) 2009 Microsoft. All rights reserved.
// </copyright>
// <author>Michael A. Hawker</author>
// Modified from Experts SDK for this Expert
//-----------------------------------------------------------------------
namespace Microsoft.NetworkMonitor.Automation
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Text;

    /// <summary>
    /// Provides an automated way to retrieve the commandline arguments passed to an Expert
    /// from the Network Monitor UI
    /// </summary>
    public class CommandLineArguments
    {
        /// <summary>
        /// Passed Capture File
        /// </summary>
        private string captureFileName;

        /// <summary>
        /// [Optional] Where the certificate is
        /// </summary>
        private string certificatePath = string.Empty;

        /// <summary>
        /// [Optional] Password for the certificate
        /// </summary>
        private string certificatePassword = string.Empty;

        /// <summary>
        /// [Optional] The Filter used by the Conversation Tree in Network Monitor
        /// </summary>
        private string conversationFilter = string.Empty;       

        /// <summary>
        /// [Optional] Where to save the file
        /// </summary>
        private string outputPath = string.Empty;

        /// <summary>
        /// [Optional] Where to save the log file
        /// </summary>
        private string logPath = string.Empty;

        /// <summary>
        /// [Optional] Start Decryption right away
        /// </summary>
        private bool startNow;

        /// <summary>
        /// [Optional] Sets if Netmon runs after decryption
        /// </summary>
        private bool runNetmon = true;

        /// <summary>
        /// Any string error message created when calling ParseCommandLineArguments
        /// </summary>
        private string errorMessage;

        /// <summary>
        /// [Optional] Will not cause any dialog boxes to appear for automation
        /// </summary>
        private bool suppressErrors;

        /// <summary>
        /// Set true if the user calls the Expert with a /? parameter only
        /// </summary>
        private bool wantHelp;

        /// <summary>
        /// Set true if the user called the Expert with no arguments
        /// </summary>
        private bool noArguments;

        /// <summary>
        /// Initializes a new instance of the CommandLineArguments class
        /// </summary>
        public CommandLineArguments()
        {
        }

        /// <summary>
        /// Gets the Capture File Name
        /// </summary>
        public string CaptureFileName
        {
            get { return this.captureFileName; }
        }

        /// <summary>
        /// Gets the Certificate Path
        /// </summary>
        public string CertificatePath
        {
            get { return this.certificatePath; }
        }

        /// <summary>
        /// Gets the Certificate Password
        /// </summary>
        public string CertificatePassword
        {
            get { return this.certificatePassword; }
        }

        /// <summary>
        /// Gets the output file path
        /// </summary>
        public string OutputPath
        {
            get { return this.outputPath; }
        }

        /// <summary>
        /// Gets the log path
        /// </summary>
        public string LogPath
        {
            get { return this.logPath; }
        }

        /// <summary>
        /// Gets a value indicating whether or not to start the Decryption right away
        /// </summary>
        public bool IsStartingNow
        {
            get { return this.startNow; }
        }

        /// <summary>
        /// Gets a value indicating whether or not to launch Netmon after decryption
        /// </summary>
        public bool IsRunningNetmonAfter
        {
            get { return this.runNetmon; }
        }

        /// <summary>
        /// Gets a value indicating whether or not to launch Netmon after decryption
        /// </summary>
        public bool IsSuppressingErrors
        {
            get { return this.suppressErrors; }
        }

        /// <summary>
        /// Gets the Conversation Filter
        /// </summary>
        public string ConversationFilter
        {
            get { return this.conversationFilter; }
        }

        /// <summary>
        /// Gets the Last Error Message
        /// </summary>
        public string LastErrorMessage
        {
            get { return this.errorMessage; }
        }

        /// <summary>
        /// Gets a value indicating whether the user has request help on using the Expert from the commandline
        /// </summary>
        public bool IsRequestingHelp
        {
            get { return this.wantHelp; }
        }

        /// <summary>
        /// Gets a value indicating whether the user has called the Expert with no arguments
        /// </summary>
        public bool IsNoArguments
        {
            get { return this.noArguments; }
        }
        
        /// <summary>
        /// Returns the usage needed for the Expert based on this class
        /// </summary>
        /// <param name="applicationName">Application Name to display</param>
        /// <returns>Returns the usage string for printing or display with the Application Name first</returns>
        public static string GetUsage(string applicationName)
        {
            return applicationName + " {NetmonOpenCaptureFile} [/s] [/n] [/e] [/o DecryptedCaptureOutputFile] [/t CertificatePath] [/p CertificatePassword] [/l LogFileLocation] [/c {NetmonConversationFilter}]";
        }

        /// <summary>
        /// Called to parse the arguments passed to the Expert's Main() function.
        /// </summary>
        /// <param name="args">Commandline arguments from Main()</param>
        /// <returns>true if successfully parsed, otherwise false, retrieve LastErrorMessage </returns>
        public bool ParseCommandLineArguments(string[] args)
        {
            this.errorMessage = null;

            // Check if we have any arguments or are asking for help
            if (args.Length == 0)
            {
                this.noArguments = true;
                return true;
            }
            else if (args.Length == 1 && args[0].Contains("/?"))
            {
                this.wantHelp = true;
                return true;
            }
            else
            {
                List<string> arguments = new List<string>(args);

                // Get Capture File Name
                this.captureFileName = arguments[0].Trim();

                arguments.RemoveAt(0);

                int skip;

                // Process Arguments until none are left
                while (arguments.Count > 0)
                {
                    skip = 1;
                    string cmd = arguments[0].Trim();

                    if (cmd.StartsWith("/s", StringComparison.CurrentCultureIgnoreCase))
                    {
                        this.startNow = true;
                    }
                    else if (cmd.StartsWith("/n", StringComparison.CurrentCultureIgnoreCase))
                    {
                        this.runNetmon = false;
                    }
                    else if (cmd.StartsWith("/e", StringComparison.CurrentCultureIgnoreCase))
                    {
                        this.suppressErrors = true;
                    } 
                    else if (cmd.StartsWith("/o", StringComparison.CurrentCultureIgnoreCase))
                    {
                        if (arguments.Count > 1)
                        {
                            this.outputPath = arguments[1].Trim();
                            skip = 2;
                        }
                        else
                        {
                            this.errorMessage = "Missing Argument for " + cmd;
                            return false;
                        }
                    }
                    else if (cmd.StartsWith("/t", StringComparison.CurrentCultureIgnoreCase))
                    {
                        if (arguments.Count > 1)
                        {
                            this.certificatePath = arguments[1].Trim();
                            skip = 2;
                        }
                        else
                        {
                            this.errorMessage = "Missing Argument for " + cmd;
                            return false;
                        }
                    }
                    else if (cmd.StartsWith("/p", StringComparison.CurrentCultureIgnoreCase))
                    {
                        if (arguments.Count > 1)
                        {
                            this.certificatePassword = arguments[1].Trim();
                            skip = 2;
                        }
                        else
                        {
                            this.errorMessage = "Missing Argument for " + cmd;
                            return false;
                        }
                    }
                    else if (cmd.StartsWith("/l", StringComparison.CurrentCultureIgnoreCase))
                    {
                        if (arguments.Count > 1)
                        {
                            this.logPath = arguments[1].Trim();
                            skip = 2;
                        }
                        else
                        {
                            this.errorMessage = "Missing Argument for " + cmd;
                            return false;
                        }
                    }   
                    else if (cmd.StartsWith("/c", StringComparison.CurrentCultureIgnoreCase))
                    {
                        if (arguments.Count > 1)
                        {
                            string substring = string.Empty;

                            int index = arguments[1].IndexOf("==");
                            if (index != -1)
                            {
                                // Special Conversation Triming used by the Decryption Expert
                                // TODO: figure out where this is used to allow for more explicit filters???
                                index = index + 4;
                                substring = arguments[1].Substring(0, index);

                                while (arguments[1].Length != index &&
                                        arguments[1].Substring(index, 1) != " ")
                                {
                                    substring = substring + arguments[1].Substring(index, 1);
                                    index++;
                                }

                                this.conversationFilter = substring;
                            }

                            skip = 2;
                        }
                    }
                    else
                    {
                        this.errorMessage = "Unrecognized parameter: " + cmd;
                        return false;
                    }

                    // Skip to next set of arguments
                    arguments.RemoveRange(0, skip);
                }
            }

            return true;
        }
    }
}

